package com.luhuiguo.gwt.mvp.dispatcher.server.spring;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.luhuiguo.gwt.mvp.dispatcher.client.SecuredDispatcherService;
import com.luhuiguo.gwt.mvp.dispatcher.server.Dispatcher;
import com.luhuiguo.gwt.mvp.dispatcher.shared.exception.AccessDeniedException;
import com.luhuiguo.gwt.mvp.dispatcher.shared.exception.ActionException;
import com.luhuiguo.gwt.mvp.dispatcher.shared.exception.AuthenticationException;
import com.luhuiguo.gwt.mvp.dispatcher.shared.exception.SecureException;
import com.luhuiguo.gwt.mvp.dispatcher.shared.exception.ServiceException;
import com.luhuiguo.gwt.mvp.dispatcher.shared.rpc.Action;
import com.luhuiguo.gwt.mvp.dispatcher.shared.rpc.Result;

public class SpringSecurityDispatcherServlet extends RemoteServiceServlet implements SecuredDispatcherService {

    private static final long serialVersionUID = -3760288559469279777L;

    private Dispatcher dispatcher;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(config
                .getServletContext());
        AutowireCapableBeanFactory beanFactory = ctx.getAutowireCapableBeanFactory();
        beanFactory.autowireBean(this);
    }

    public Result execute(Action<?> action) throws ActionException, ServiceException, SecureException {
        try {
            return getDispatcher().execute(action);
        } catch (org.springframework.security.access.AccessDeniedException e) {
            throw new AccessDeniedException(e.getMessage(), e);
        } catch (org.springframework.security.core.AuthenticationException e) {
            throw new AuthenticationException(e.getMessage(), e);
        } catch (RuntimeException e) {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    public Dispatcher getDispatcher() {
        return dispatcher;
    }

    @Autowired
    @Required
    public void setDispatcher(Dispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }

}
